#include "av.h"

static
int lua_register_av_consts(lua_State * L, const char * tname, lua_constant * c) {
	lua_pushstring(L, tname);
	lua_newtable(L);
	while (c->name) {
		lua_pushstring(L, c->name);
		lua_pushboolean(L, 1);
		lua_settable(L, -3);
		c++;
	}
	lua_settable(L, -3);

	return 0;
}

static
void push_constant(lua_State * L, int value, lua_constant * c) {
	while (c->name) {
		if (c->value == value) {
			lua_pushstring(L, c->name);
			return ;
		}
		c++;
	}
}

static
int check_constant(lua_State * L, int narg, const char * tname, lua_constant * c) {
	const char * s = lua_tostring(L, narg);
	while (c->name) {
		if (strcmp(s, c->name) == 0) {
			return c->value;
		}
		c++;
	}
	luaL_error(L, "Bad argument %d, valid %s expected", narg, tname);
	return -1;
}

lua_constant codecs[] = {
	{ "none", CODEC_ID_NONE, },
	{ "mpeg1video", CODEC_ID_MPEG1VIDEO, },
	{ "mpeg2video", CODEC_ID_MPEG2VIDEO, },
	{ "mpeg2video_xvmc", CODEC_ID_MPEG2VIDEO_XVMC, },
	{ "h261", CODEC_ID_H261, },
	{ "h263", CODEC_ID_H263, },
	{ "rv10", CODEC_ID_RV10, },
	{ "rv20", CODEC_ID_RV20, },
	{ "mjpeg", CODEC_ID_MJPEG, },
	{ "mjpegb", CODEC_ID_MJPEGB, },
	{ "ljpeg", CODEC_ID_LJPEG, },
	{ "sp5x", CODEC_ID_SP5X, },
	{ "jpegls", CODEC_ID_JPEGLS, },
	{ "mpeg4", CODEC_ID_MPEG4, },
	{ "rawvideo", CODEC_ID_RAWVIDEO, },
	{ "msmpeg4v1", CODEC_ID_MSMPEG4V1, },
	{ "msmpeg4v2", CODEC_ID_MSMPEG4V2, },
	{ "msmpeg4v3", CODEC_ID_MSMPEG4V3, },
	{ "wmv1", CODEC_ID_WMV1, },
	{ "wmv2", CODEC_ID_WMV2, },
	{ "h263p", CODEC_ID_H263P, },
	{ "h263i", CODEC_ID_H263I, },
	{ "flv1", CODEC_ID_FLV1, },
	{ "svq1", CODEC_ID_SVQ1, },
	{ "svq3", CODEC_ID_SVQ3, },
	{ "dvvideo", CODEC_ID_DVVIDEO, },
	{ "huffyuv", CODEC_ID_HUFFYUV, },
	{ "cyuv", CODEC_ID_CYUV, },
	{ "h264", CODEC_ID_H264, },
	{ "indeo3", CODEC_ID_INDEO3, },
	{ "vp3", CODEC_ID_VP3, },
	{ "theora", CODEC_ID_THEORA, },
	{ "asv1", CODEC_ID_ASV1, },
	{ "asv2", CODEC_ID_ASV2, },
	{ "ffv1", CODEC_ID_FFV1, },
	{ "4xm", CODEC_ID_4XM, },
	{ "vcr1", CODEC_ID_VCR1, },
	{ "cljr", CODEC_ID_CLJR, },
	{ "mdec", CODEC_ID_MDEC, },
	{ "roq", CODEC_ID_ROQ, },
	{ "interplay_video", CODEC_ID_INTERPLAY_VIDEO, },
	{ "xan_wc3", CODEC_ID_XAN_WC3, },
	{ "xan_wc4", CODEC_ID_XAN_WC4, },
	{ "rpza", CODEC_ID_RPZA, },
	{ "cinepak", CODEC_ID_CINEPAK, },
	{ "ws_vqa", CODEC_ID_WS_VQA, },
	{ "msrle", CODEC_ID_MSRLE, },
	{ "msvideo1", CODEC_ID_MSVIDEO1, },
	{ "idcin", CODEC_ID_IDCIN, },
	{ "8bps", CODEC_ID_8BPS, },
	{ "smc", CODEC_ID_SMC, },
	{ "flic", CODEC_ID_FLIC, },
	{ "truemotion1", CODEC_ID_TRUEMOTION1, },
	{ "vmdvideo", CODEC_ID_VMDVIDEO, },
	{ "mszh", CODEC_ID_MSZH, },
	{ "zlib", CODEC_ID_ZLIB, },
	{ "qtrle", CODEC_ID_QTRLE, },
	{ "snow", CODEC_ID_SNOW, },
	{ "tscc", CODEC_ID_TSCC, },
	{ "ulti", CODEC_ID_ULTI, },
	{ "qdraw", CODEC_ID_QDRAW, },
	{ "vixl", CODEC_ID_VIXL, },
	{ "qpeg", CODEC_ID_QPEG, },
	{ "xvid", CODEC_ID_XVID, },
	{ "png", CODEC_ID_PNG, },
	{ "ppm", CODEC_ID_PPM, },
	{ "pbm", CODEC_ID_PBM, },
	{ "pgm", CODEC_ID_PGM, },
	{ "pgmyuv", CODEC_ID_PGMYUV, },
	{ "pam", CODEC_ID_PAM, },
	{ "ffvhuff", CODEC_ID_FFVHUFF, },
	{ "rv30", CODEC_ID_RV30, },
	{ "rv40", CODEC_ID_RV40, },
	{ "vc1", CODEC_ID_VC1, },
	{ "wmv3", CODEC_ID_WMV3, },
	{ "loco", CODEC_ID_LOCO, },
	{ "wnv1", CODEC_ID_WNV1, },
	{ "aasc", CODEC_ID_AASC, },
	{ "indeo2", CODEC_ID_INDEO2, },
	{ "fraps", CODEC_ID_FRAPS, },
	{ "truemotion2", CODEC_ID_TRUEMOTION2, },
	{ "bmp", CODEC_ID_BMP, },
	{ "cscd", CODEC_ID_CSCD, },
	{ "mmvideo", CODEC_ID_MMVIDEO, },
	{ "zmbv", CODEC_ID_ZMBV, },
	{ "avs", CODEC_ID_AVS, },
	{ "smackvideo", CODEC_ID_SMACKVIDEO, },
	{ "nuv", CODEC_ID_NUV, },
	{ "kmvc", CODEC_ID_KMVC, },
	{ "flashsv", CODEC_ID_FLASHSV, },
	{ "cavs", CODEC_ID_CAVS, },
	{ "jpeg2000", CODEC_ID_JPEG2000, },
	{ "vmnc", CODEC_ID_VMNC, },
	{ "vp5", CODEC_ID_VP5, },
	{ "vp6", CODEC_ID_VP6, },
	{ "vp6f", CODEC_ID_VP6F, },
	{ "targa", CODEC_ID_TARGA, },
	{ "dsicinvideo", CODEC_ID_DSICINVIDEO, },
	{ "tiertexseqvideo", CODEC_ID_TIERTEXSEQVIDEO, },
	{ "tiff", CODEC_ID_TIFF, },
	{ "gif", CODEC_ID_GIF, },
	{ "ffh264", CODEC_ID_FFH264, },
	{ "dxa", CODEC_ID_DXA, },
	{ "dnxhd", CODEC_ID_DNXHD, },
	{ "thp", CODEC_ID_THP, },
	{ "sgi", CODEC_ID_SGI, },
	{ "c93", CODEC_ID_C93, },
	{ "bethsoftvid", CODEC_ID_BETHSOFTVID, },
	{ "ptx", CODEC_ID_PTX, },
	{ "txd", CODEC_ID_TXD, },
	{ "vp6a", CODEC_ID_VP6A, },
	{ "amv", CODEC_ID_AMV, },
	{ "vb", CODEC_ID_VB, },
	{ "pcx", CODEC_ID_PCX, },
	{ "sunrast", CODEC_ID_SUNRAST, },
	{ "indeo4", CODEC_ID_INDEO4, },
	{ "indeo5", CODEC_ID_INDEO5, },
	{ "mimic", CODEC_ID_MIMIC, },
	{ "rl2", CODEC_ID_RL2, },
	{ "8svx_exp", CODEC_ID_8SVX_EXP, },
	{ "8svx_fib", CODEC_ID_8SVX_FIB, },
	{ "escape124", CODEC_ID_ESCAPE124, },
	{ "dirac", CODEC_ID_DIRAC, },
	{ "bfi", CODEC_ID_BFI, },
	{ "cmv", CODEC_ID_CMV, },
	{ "motionpixels", CODEC_ID_MOTIONPIXELS, },
	{ "tgv", CODEC_ID_TGV, },
	{ "tgq", CODEC_ID_TGQ, },
	{ "tqi", CODEC_ID_TQI, },
	{ "pcm_s16le", CODEC_ID_PCM_S16LE, },
	{ "pcm_s16be", CODEC_ID_PCM_S16BE, },
	{ "pcm_u16le", CODEC_ID_PCM_U16LE, },
	{ "pcm_u16be", CODEC_ID_PCM_U16BE, },
	{ "pcm_s8", CODEC_ID_PCM_S8, },
	{ "pcm_u8", CODEC_ID_PCM_U8, },
	{ "pcm_mulaw", CODEC_ID_PCM_MULAW, },
	{ "pcm_alaw", CODEC_ID_PCM_ALAW, },
	{ "pcm_s32le", CODEC_ID_PCM_S32LE, },
	{ "pcm_s32be", CODEC_ID_PCM_S32BE, },
	{ "pcm_u32le", CODEC_ID_PCM_U32LE, },
	{ "pcm_u32be", CODEC_ID_PCM_U32BE, },
	{ "pcm_s24le", CODEC_ID_PCM_S24LE, },
	{ "pcm_s24be", CODEC_ID_PCM_S24BE, },
	{ "pcm_u24le", CODEC_ID_PCM_U24LE, },
	{ "pcm_u24be", CODEC_ID_PCM_U24BE, },
	{ "pcm_s24daud", CODEC_ID_PCM_S24DAUD, },
	{ "pcm_zork", CODEC_ID_PCM_ZORK, },
	{ "pcm_s16le_planar", CODEC_ID_PCM_S16LE_PLANAR, },
	{ "pcm_dvd", CODEC_ID_PCM_DVD, },
	{ "pcm_f32be", CODEC_ID_PCM_F32BE, },
	{ "pcm_f32le", CODEC_ID_PCM_F32LE, },
	{ "pcm_f64be", CODEC_ID_PCM_F64BE, },
	{ "pcm_f64le", CODEC_ID_PCM_F64LE, },
	{ "adpcm_ima_qt", CODEC_ID_ADPCM_IMA_QT, },
	{ "adpcm_ima_wav", CODEC_ID_ADPCM_IMA_WAV, },
	{ "adpcm_ima_dk3", CODEC_ID_ADPCM_IMA_DK3, },
	{ "adpcm_ima_dk4", CODEC_ID_ADPCM_IMA_DK4, },
	{ "adpcm_ima_ws", CODEC_ID_ADPCM_IMA_WS, },
	{ "adpcm_ima_smjpeg", CODEC_ID_ADPCM_IMA_SMJPEG, },
	{ "adpcm_ms", CODEC_ID_ADPCM_MS, },
	{ "adpcm_4xm", CODEC_ID_ADPCM_4XM, },
	{ "adpcm_xa", CODEC_ID_ADPCM_XA, },
	{ "adpcm_adx", CODEC_ID_ADPCM_ADX, },
	{ "adpcm_ea", CODEC_ID_ADPCM_EA, },
	{ "adpcm_g726", CODEC_ID_ADPCM_G726, },
	{ "adpcm_ct", CODEC_ID_ADPCM_CT, },
	{ "adpcm_swf", CODEC_ID_ADPCM_SWF, },
	{ "adpcm_yamaha", CODEC_ID_ADPCM_YAMAHA, },
	{ "adpcm_sbpro_4", CODEC_ID_ADPCM_SBPRO_4, },
	{ "adpcm_sbpro_3", CODEC_ID_ADPCM_SBPRO_3, },
	{ "adpcm_sbpro_2", CODEC_ID_ADPCM_SBPRO_2, },
	{ "adpcm_thp", CODEC_ID_ADPCM_THP, },
	{ "adpcm_ima_amv", CODEC_ID_ADPCM_IMA_AMV, },
	{ "adpcm_ea_r1", CODEC_ID_ADPCM_EA_R1, },
	{ "adpcm_ea_r3", CODEC_ID_ADPCM_EA_R3, },
	{ "adpcm_ea_r2", CODEC_ID_ADPCM_EA_R2, },
	{ "adpcm_ima_ea_sead", CODEC_ID_ADPCM_IMA_EA_SEAD, },
	{ "adpcm_ima_ea_eacs", CODEC_ID_ADPCM_IMA_EA_EACS, },
	{ "adpcm_ea_xas", CODEC_ID_ADPCM_EA_XAS, },
	{ "adpcm_ea_maxis_xa", CODEC_ID_ADPCM_EA_MAXIS_XA, },
	{ "adpcm_ima_iss", CODEC_ID_ADPCM_IMA_ISS, },
	{ "amr_nb", CODEC_ID_AMR_NB, },
	{ "amr_wb", CODEC_ID_AMR_WB, },
	{ "ra_144", CODEC_ID_RA_144, },
	{ "ra_288", CODEC_ID_RA_288, },
	{ "roq_dpcm", CODEC_ID_ROQ_DPCM, },
	{ "interplay_dpcm", CODEC_ID_INTERPLAY_DPCM, },
	{ "xan_dpcm", CODEC_ID_XAN_DPCM, },
	{ "sol_dpcm", CODEC_ID_SOL_DPCM, },
	{ "mp2", CODEC_ID_MP2, },
	{ "mp3", CODEC_ID_MP3, },
	{ "aac", CODEC_ID_AAC, },
	{ "ac3", CODEC_ID_AC3, },
	{ "dts", CODEC_ID_DTS, },
	{ "vorbis", CODEC_ID_VORBIS, },
	{ "dvaudio", CODEC_ID_DVAUDIO, },
	{ "wmav1", CODEC_ID_WMAV1, },
	{ "wmav2", CODEC_ID_WMAV2, },
	{ "mace3", CODEC_ID_MACE3, },
	{ "mace6", CODEC_ID_MACE6, },
	{ "vmdaudio", CODEC_ID_VMDAUDIO, },
	{ "sonic", CODEC_ID_SONIC, },
	{ "sonic_ls", CODEC_ID_SONIC_LS, },
	{ "flac", CODEC_ID_FLAC, },
	{ "mp3adu", CODEC_ID_MP3ADU, },
	{ "mp3on4", CODEC_ID_MP3ON4, },
	{ "shorten", CODEC_ID_SHORTEN, },
	{ "alac", CODEC_ID_ALAC, },
	{ "westwood_snd1", CODEC_ID_WESTWOOD_SND1, },
	{ "gsm", CODEC_ID_GSM, },
	{ "qdm2", CODEC_ID_QDM2, },
	{ "cook", CODEC_ID_COOK, },
	{ "truespeech", CODEC_ID_TRUESPEECH, },
	{ "tta", CODEC_ID_TTA, },
	{ "smackaudio", CODEC_ID_SMACKAUDIO, },
	{ "qcelp", CODEC_ID_QCELP, },
	{ "wavpack", CODEC_ID_WAVPACK, },
	{ "dsicinaudio", CODEC_ID_DSICINAUDIO, },
	{ "imc", CODEC_ID_IMC, },
	{ "musepack7", CODEC_ID_MUSEPACK7, },
	{ "mlp", CODEC_ID_MLP, },
	{ "gsm_ms", CODEC_ID_GSM_MS, },
	{ "atrac3", CODEC_ID_ATRAC3, },
	{ "voxware", CODEC_ID_VOXWARE, },
	{ "ape", CODEC_ID_APE, },
	{ "nellymoser", CODEC_ID_NELLYMOSER, },
	{ "musepack8", CODEC_ID_MUSEPACK8, },
	{ "speex", CODEC_ID_SPEEX, },
	{ "wmavoice", CODEC_ID_WMAVOICE, },
	{ "wmapro", CODEC_ID_WMAPRO, },
	{ "wmalossless", CODEC_ID_WMALOSSLESS, },
	{ "atrac3p", CODEC_ID_ATRAC3P, },
	{ "eac3", CODEC_ID_EAC3, },
	{ "sipr", CODEC_ID_SIPR, },
	{ "mp1", CODEC_ID_MP1, },
	{ "dvd_subtitle", CODEC_ID_DVD_SUBTITLE, },
	{ "dvb_subtitle", CODEC_ID_DVB_SUBTITLE, },
	{ "text", CODEC_ID_TEXT, },
	{ "xsub", CODEC_ID_XSUB, },
	{ "ssa", CODEC_ID_SSA, },
	{ "mov_text", CODEC_ID_MOV_TEXT, },
	{ "ttf", CODEC_ID_TTF, },
	{ "probe", CODEC_ID_PROBE, },
	{ "mpeg2ts", CODEC_ID_MPEG2TS, },
	{ NULL, 0, },
};

extern
void lua_push_codec_id(lua_State * L, enum CodecID cid) {
	push_constant(L, (int) cid, codecs);
}

extern
enum CodecID lua_check_codec_id(lua_State * L, int narg) {
	return (enum CodecID) check_constant(L, narg, "codec", codecs);
}

lua_constant codec_types[] = {
	{ "unknown", CODEC_TYPE_UNKNOWN, },
	{ "video", CODEC_TYPE_VIDEO, },
	{ "audio", CODEC_TYPE_AUDIO, },
	{ "data", CODEC_TYPE_DATA, },
	{ "subtitle", CODEC_TYPE_SUBTITLE, },
	{ "attachment", CODEC_TYPE_ATTACHMENT, },
	{ NULL, 0, },
};

extern
void lua_push_codec_type(lua_State * L, enum CodecType ctype) {
	push_constant(L, (int) ctype, codec_types);
}

extern
enum CodecType lua_check_codec_type(lua_State * L, int narg) {
	return (enum CodecType) check_constant(L, narg, "codec_type", codec_types);
}

lua_constant me_types[] = {
	{ "zero", ME_ZERO, },
	{ "full", ME_FULL, },
	{ "log", ME_LOG, },
	{ "phods", ME_PHODS, },
	{ "epzs", ME_EPZS, },
	{ "x1", ME_X1, },
	{ "hex", ME_HEX, },
	{ "umh", ME_UMH, },
	{ "iter", ME_ITER, },
	{ "tesa", ME_TESA, },
	{ NULL, 0, },
};

extern
void lua_push_me_method(lua_State * L, enum Motion_Est_ID id) {
	push_constant(L, (int) id, me_types);
}

extern
enum Motion_Est_ID lua_check_me_method(lua_State * L, int narg) {
	return (enum Motion_Est_ID) check_constant(L, narg, "me_method", me_types);
}

lua_constant pixel_formats[] = {
	{ "none", PIX_FMT_NONE, },
	{ "yuv420p", PIX_FMT_YUV420P, },
	{ "yuyv422", PIX_FMT_YUYV422, },
	{ "rgb24", PIX_FMT_RGB24, },
	{ "bgr24", PIX_FMT_BGR24, },
	{ "yuv422p", PIX_FMT_YUV422P, },
	{ "yuv444p", PIX_FMT_YUV444P, },
	{ "rgb32", PIX_FMT_RGB32, },
	{ "yuv410p", PIX_FMT_YUV410P, },
	{ "yuv411p", PIX_FMT_YUV411P, },
	{ "rgb565", PIX_FMT_RGB565, },
	{ "rgb555", PIX_FMT_RGB555, },
	{ "gray8", PIX_FMT_GRAY8, },
	{ "monowhite", PIX_FMT_MONOWHITE, },
	{ "monoblack", PIX_FMT_MONOBLACK, },
	{ "pal8", PIX_FMT_PAL8, },
	{ "yuvj420p", PIX_FMT_YUVJ420P, },
	{ "yuvj422p", PIX_FMT_YUVJ422P, },
	{ "yuvj444p", PIX_FMT_YUVJ444P, },
	{ "xvmc_mpeg2_mc", PIX_FMT_XVMC_MPEG2_MC, },
	{ "xvmc_mpeg2_idct", PIX_FMT_XVMC_MPEG2_IDCT, },
	{ "uyvy422", PIX_FMT_UYVY422, },
	{ "uyyvyy411", PIX_FMT_UYYVYY411, },
	{ "bgr32", PIX_FMT_BGR32, },
	{ "bgr565", PIX_FMT_BGR565, },
	{ "bgr555", PIX_FMT_BGR555, },
	{ "bgr8", PIX_FMT_BGR8, },
	{ "bgr4", PIX_FMT_BGR4, },
	{ "bgr4_byte", PIX_FMT_BGR4_BYTE, },
	{ "rgb8", PIX_FMT_RGB8, },
	{ "rgb4", PIX_FMT_RGB4, },
	{ "rgb4_byte", PIX_FMT_RGB4_BYTE, },
	{ "nv12", PIX_FMT_NV12, },
	{ "nv21", PIX_FMT_NV21, },
	{ "rgb32_1", PIX_FMT_RGB32_1, },
	{ "bgr32_1", PIX_FMT_BGR32_1, },
	{ "gray16be", PIX_FMT_GRAY16BE, },
	{ "gray16le", PIX_FMT_GRAY16LE, },
	{ "yuv440p", PIX_FMT_YUV440P, },
	{ "yuvj440p", PIX_FMT_YUVJ440P, },
	{ "yuva420p", PIX_FMT_YUVA420P, },
	{ "vdpau_h264", PIX_FMT_VDPAU_H264, },
	{ "vdpau_mpeg1", PIX_FMT_VDPAU_MPEG1, },
	{ "vdpau_mpeg2", PIX_FMT_VDPAU_MPEG2, },
	{ "vdpau_wmv3", PIX_FMT_VDPAU_WMV3, },
	{ "vdpau_vc1", PIX_FMT_VDPAU_VC1, },
	{ "rgb48be", PIX_FMT_RGB48BE, },
	{ "rgb48le", PIX_FMT_RGB48LE, },
	{ "vaapi_moco", PIX_FMT_VAAPI_MOCO, },
	{ "vaapi_idct", PIX_FMT_VAAPI_IDCT, },
	{ "vaapi_vld", PIX_FMT_VAAPI_VLD, },
	{ NULL, 0, },
};

extern
void lua_push_pixel_format(lua_State * L, enum PixelFormat id) {
	push_constant(L, (int) id, pixel_formats);
}

extern
enum PixelFormat lua_check_pixel_format(lua_State * L, int narg) {
	return (enum Motion_Est_ID) check_constant(L, narg, "pixel_format", pixel_formats);
}

lua_constant sample_formats[] = {
	{ "none", SAMPLE_FMT_NONE, },
	{ "u8", SAMPLE_FMT_U8, },
	{ "s16", SAMPLE_FMT_S16, },
	{ "s32", SAMPLE_FMT_S32, },
	{ "flt", SAMPLE_FMT_FLT, },
	{ "dbl", SAMPLE_FMT_DBL, },
	{ NULL, 0, },
};

extern
void lua_push_sample_format(lua_State * L, enum SampleFormat id) {
	push_constant(L, (int) id, sample_formats);
}

extern
enum SampleFormat lua_check_sample_format(lua_State * L, int narg) {
	return (enum Motion_Est_ID) check_constant(L, narg, "sample_format", sample_formats);
}



extern
int lua_register_av_constants(lua_State * L) {
	lua_register_av_consts(L, "CODECS", codecs);
	lua_register_av_consts(L, "CODEC_TYPES", codec_types);
	lua_register_av_consts(L, "ME_METHODS", me_types);
	lua_register_av_consts(L, "PIXEL_FORMATS", pixel_formats);
	lua_register_av_consts(L, "SAMPLE_FORMATS", sample_formats);

	return 0;
}

